﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NGenORM.Library
{
    public class File
    {

        public List<Obj> Objects {get; set;}

        private string ProperCase(string str) {
            // if not value is provided throw an exception
            if (string.IsNullOrEmpty(str))
            throw new ArgumentException("A null value cannot be converted", str);
 
            if (str.Length < 2) {
                return str.ToUpper();
            }
 
            string converted = str.Substring(0, 1).Trim().ToUpper();
 
            for (int i = 1; i < str.Length; i++) {
                converted = (Char.IsUpper(str[i])) ? converted += " " : converted += str[i];
            }
 
            return converted;
        }

        private String GetDBType(int DataType) { 
            
            string Type = "";

            switch (DataType)
            {
                case 34: Type = "SqlDbType.Image"; break;
                case 35: Type = "SqlDbType.Text"; break;
                case 48: Type = "SqlDbType.TinyInt"; break;
                case 52: Type = "SqlDbType.SmallInt"; break;
                case 56: Type = "SqlDbType.Int"; break;
                case 58: Type = "SqlDbType.SmallDateTime"; break;
                case 59: Type = "SqlDbType.Real"; break;
                case 60: Type = "SqlDbType.Money"; break;
                case 61: Type = "SqlDbType.DateTime"; break;
                case 62: Type = "SqlDbType.Float"; break;
                case 99: Type = "SqlDbType.NText"; break;
                case 104: Type = "SqlDbType.Bit"; break;
                case 106: Type = "SqlDbType.Decimal"; break;
                case 108: Type = "SqlDbType.Decimal"; break;
                case 122: Type = "SqlDbType.SmallMoney"; break;
                case 127: Type = "SqlDbType.BigInt"; break;
                case 165: Type = "SqlDbType.VarBinary"; break;
                case 167: Type = "SqlDbType.VarChar"; break;
                case 173: Type = "SqlDbType.Binary"; break;
                case 175: Type = "SqlDbType.Char"; break;
                case 231: Type = "SqlDbType.NVarChar"; break;
                case 239: Type = "SqlDbType.NChar"; break;
                default: Type = ""; break;
            }

            return Type;

        }

        private String GetCodeType(int DataType) { 
            
            string Type = "";

            switch (DataType)
            {
                case 34: Type = "Image"; break; //Image
                case 35: Type = "String"; break; //Text
                case 48: Type = "Integer"; break; //TinyInt
                case 52: Type = "Integer"; break; //SmallInt
                case 56: Type = "Integer"; break; //Int
                case 58: Type = "DateTime"; break; //SmallDateTime
                case 59: Type = "Double"; break; //Real
                case 60: Type = "Decimal"; break; //Money
                case 61: Type = "DateTime"; break; //DateTime
                case 62: Type = "Double"; break; //Float
                case 99: Type = "String"; break; //NText
                case 104: Type = "Boolean"; break; //Bit
                case 106: Type = "Decimal"; break; //Decimal
                case 108: Type = "Double"; break;//Numeric
                case 122: Type = "Double"; break;//SmallMoney
                case 127: Type = "Integer"; break; //BigInt
                case 165: Type = "VarBinary"; break;
                case 167: Type = "String"; break; //VarChar
                case 173: Type = "Binary"; break;
                case 175: Type = "String"; break; //Char
                case 231: Type = "String"; break; //NVarChar
                case 239: Type = "String"; break; //NChar
                default: Type = ""; break;
            }

            return Type;

        }

        private StringBuilder CreateBeginClass(Obj obj) { 
        
            if (obj.Project.ClassAlias == null) {
                obj.Project.ClassAlias = "";
            }
            
            string aux = obj.Project.ClassAlias + ProperCase(obj.ObjectName.ToString());
            StringBuilder sb = new System.Text.StringBuilder();

            switch (obj.Project.LanguageType) {

                case LanguageType.CSharp:

                    switch (obj.Project.ObjectType)
                    {
                        case ObjectType.Entity:

                            sb.Append("public Class " + aux + "").AppendLine();
                            sb.Append("{").AppendLine();
                            sb.Append("").AppendLine();
                            break;

                        case ObjectType.Persistence:

                            sb.Append("Public Class " + aux + "DAO : " + aux + "").AppendLine();
                            sb.Append("{").AppendLine();
                            sb.Append("").AppendLine();
                            break;

                        case ObjectType.Service:
                            sb.Append("Public Class " + aux + "Servico").AppendLine();
                            sb.Append("{").AppendLine();
                            sb.Append("").AppendLine();
                            break;
                    }
                    break;

                case LanguageType.VB:

                    switch (obj.Project.ObjectType)
                    {
                        case ObjectType.Entity:

                            sb.Append("Public Class " + aux + "").AppendLine();
                            sb.Append("").AppendLine();
                            break;

                        case ObjectType.Persistence:

                            sb.Append("Public Class " + aux + "DAO").AppendLine();
                            sb.Append("    Inherits " + aux + "").AppendLine();
                            sb.Append("").AppendLine();
                            break;

                        case ObjectType.Service:
                            sb.Append("Public Class " + aux + "Servico").AppendLine();
                            sb.Append("").AppendLine();
                            break;
                    }
                    break;
            }

            return sb;

        }

        private StringBuilder CreateEndClass(Obj obj)
        {

            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            switch (obj.Project.LanguageType)
            {
                     
                case LanguageType.CSharp:
                    sb.Append("}").AppendLine();
                    break;

                case LanguageType.VB:
                    sb.Append("End Class").AppendLine();
                    break;
            }

            return sb;

        }

        private StringBuilder CreateComment(Obj obj) { 

            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            if (obj.Project.MethodComment == true)
            {

                if (obj.Project.ObjectType == ObjectType.Persistence || obj.Project.ObjectType == ObjectType.Service)
                {

                    switch (obj.Project.LanguageType)
                    {

                        case LanguageType.CSharp:
                            sb.Append("").AppendLine();
                            break;

                        case LanguageType.VB:
                            foreach (MethodType item in obj.Project.MethodTypes)
                            {

                                switch (item)
                                {
                                    case MethodType.Save:
                                        sb.Append("    ''' Método para Salvar(Inserir/Atualizar) objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                    case MethodType.Update:
                                        sb.Append("    ''' Método para Atualizar objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                    case MethodType.Insert:
                                        sb.Append("    ''' Método para Inserir objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                    case MethodType.Delete:
                                        sb.Append("    ''' Método para Excluir objetos na Tabela " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                    case MethodType.ListOne:
                                        sb.Append("    ''' Método para Retornar um objeto da Tabela " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                    case MethodType.ListAll:
                                        sb.Append("    ''' Método para Retornar uma lista de objetos da Tabela " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                    case MethodType.Execute:
                                        sb.Append("    ''' Método para Executar o objeto " + obj.ObjectName.ToString() + "").AppendLine();
                                        break;
                                }

                            }
                            sb.Append("    ''' </summary>").AppendLine();
                            sb.Append("    ''' <returns>Retorna True se o método for executado com Sucesso e Falso para Erro.</returns>").AppendLine();
                            sb.Append("    ''' <remarks></remarks>").AppendLine();
                            break;
                    }

                }

                else {
                    sb.Append("");
                }

            }

            else {
                sb.Append("");
            }

            return sb;

        }

        private StringBuilder CreateHeaderClass(Obj obj) {

            StringBuilder sb = new StringBuilder();

            if (obj.Project.ClassHeader == true){
                switch (obj.Project.LanguageType)
                {
                    case LanguageType.CSharp:
                        sb.Append("//-----------------------------------------------------").AppendLine();
                        sb.Append("//Classe criada automaticamente pelo NGenORM").AppendLine();
                        sb.Append("//Para maiores informações: www.4nsoftsolutions.com.br").AppendLine();
                        sb.Append("//Data de Criação: " + DateTime.Now.ToString() + "").AppendLine();
                        sb.Append("//Classe criada para manipular o objeto: " + obj.ObjectName.ToString() + "").AppendLine();
                        sb.Append("//-----------------------------------------------------").AppendLine();
                        sb.Append("").AppendLine();
                        break;

                    case LanguageType.VB:
                        sb.Append("'-----------------------------------------------------").AppendLine();
                        sb.Append("'Classe criada automaticamente pelo NGenORM").AppendLine();
                        sb.Append("'Para maiores informações: www.4nsoftsolutions.com.br").AppendLine();
                        sb.Append("'Data de Criação: " + DateTime.Now.ToString() + "").AppendLine();
                        sb.Append("'Classe criada para manipular o objeto: " + obj.ObjectName.ToString() + "").AppendLine();
                        sb.Append("'-----------------------------------------------------").AppendLine();
                        sb.Append("").AppendLine();
                        break;
                }
            }
            else {
                sb.Append("");
            }

            return sb;

        }

        private StringBuilder CreateNamespace(Obj obj) {

            StringBuilder sb = new StringBuilder();

            switch (obj.Project.LanguageType)
            {
                case LanguageType.CSharp:

                    sb.Append("#region Namespace").AppendLine();
                    sb.Append("").AppendLine();

                    switch (obj.Project.ObjectType)
	                {
                        case ObjectType.Entity:
                            sb.Append("").AppendLine();
                            break;
                        case ObjectType.Persistence:
                            sb.Append("using " + obj.Project.ProjectName.ToString() + ".Entity;").AppendLine();
                            sb.Append("using " + obj.Project.ProjectName.ToString() + ".Util;").AppendLine();
                            break;
                        case ObjectType.Service:
                            sb.Append("using " + obj.Project.ProjectName.ToString() + ".Persistence;").AppendLine();
                            sb.Append("using " + obj.Project.ProjectName.ToString() + ".Entity;").AppendLine();
                            break;
	                }
                    break;

                    sb.Append("").AppendLine();
                    sb.Append("#endregion").AppendLine();
                    sb.Append("").AppendLine();
                    
                case LanguageType.VB:

                    sb.Append("#Region " + "\"Namespace\"").AppendLine();
                    sb.Append("").AppendLine();

                    switch (obj.Project.ObjectType)
                    {
                        case ObjectType.Entity:
                            sb.Append("").AppendLine();
                            break;
                        case ObjectType.Persistence:
                            sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Entity").AppendLine();
                            sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Util").AppendLine();
                            break;
                        case ObjectType.Service:
                            sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Persistence").AppendLine();
                            sb.Append("Imports " + obj.Project.ProjectName.ToString() + ".Entity").AppendLine();
                            break;
                    }
                    break;

                    sb.Append("").AppendLine();
                    sb.Append("#End Region").AppendLine();
                    sb.Append("").AppendLine();
            }

            return sb;

        }

        private StringBuilder CreateConstructorService(Obj obj) {

            StringBuilder sb = new StringBuilder();

            switch (obj.Project.LanguageType)
            {
                case LanguageType.CSharp:

                    sb.Append("#region Construtor").AppendLine();
                    sb.Append("").AppendLine();
                    sb.Append("    /// <summary>").AppendLine();
                    sb.Append("    /// Singleton Pattern").AppendLine();
                    sb.Append("    /// </summary>").AppendLine();
                    sb.Append("    /// <remarks></remarks>").AppendLine();
                    sb.Append("    private void CreateDAO() {").AppendLine();
                    sb.Append("        If (Dao == null) {").AppendLine();
                    sb.Append("            Dao = New " + ProperCase(obj.ObjectName.ToString()) + "DAO();").AppendLine();
                    sb.Append("        }").AppendLine();
                    sb.Append("    }").AppendLine();
                    sb.Append("").AppendLine();
                    sb.Append("    Public Sub " + obj.ObjectName.ToString() + "Service() {").AppendLine();
                    sb.Append("        CreateDAO();").AppendLine();
                    sb.Append("    }").AppendLine();
                    sb.Append("").AppendLine();

                    sb.Append("").AppendLine();
                    sb.Append("#endregion").AppendLine();
                    sb.Append("").AppendLine();
                    break;

                case LanguageType.VB:

                    sb.Append("#Region \"Construtor\"").AppendLine();
                    sb.Append("").AppendLine();
                    sb.Append("    ''' <summary>").AppendLine();
                    sb.Append("    ''' Singleton Pattern").AppendLine();
                    sb.Append("    ''' </summary>").AppendLine();
                    sb.Append("    ''' <remarks></remarks>").AppendLine();
                    sb.Append("    Private Sub CreateDAO()").AppendLine();
                    sb.Append("        If Dao is Nothing Then").AppendLine();
                    sb.Append("            Dao = New " + ProperCase(obj.ObjectName.ToString()) + "DAO()").AppendLine();
                    sb.Append("        End If").AppendLine();
                    sb.Append("    End Sub").AppendLine();
                    sb.Append("").AppendLine();
                    sb.Append("    Public Sub New()").AppendLine();
                    sb.Append("        CreateDAO()").AppendLine();
                    sb.Append("    End Sub").AppendLine();
                    sb.Append("").AppendLine();

                    sb.Append("").AppendLine();
                    sb.Append("#End Region").AppendLine();
                    sb.Append("").AppendLine();
                    break;
            }

        return sb;

        }

    }

}
